home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Linux Cubed Series 7: Sunsite
/
Linux Cubed Series 7 - Sunsite Vol 1.iso
/
system
/
admin
/
linuxcon.000
/
linuxcon
/
linuxconf-1.6
/
askrunlevel
/
lilo.c
< prev
next >
Wrap
C/C++ Source or Header
|
1996-05-19
|
22KB
|
881 lines
#include <stdlib.h>
#include <string.h>
#include <limits.h>
#include "../misc/misc.h"
#include "askrunlevel.h"
#include "../netconf/netconf.h"
#include "../fstab/fstab.h"
#include "../paths.h"
#include "askrunlevel.m"
static HELP_FILE help_lilo (HELP_ASKRUN,"lilo");
static CONFIG_FILE f_lilo (ETC_LILO_CONF,help_lilo,CONFIGF_MANAGED);
static CONFIG_FILE f_makefile (USR_SRC_LINUX_MAKEFILE,help_lilo,CONFIGF_NONE);
/*
One configuration
*/
class LILO_PARM{
public:
int ramdisk; // Size of the ramdisk or no ramdisk
char read_only;
SSTRING vga;
SSTRING root;
SSTRING append;
/*~PROTOBEG~ LILO_PARM */
public:
LILO_PARM (void);
/*~PROTOEND~ LILO_PARM */
};
PUBLIC LILO_PARM::LILO_PARM()
{
ramdisk = 0;
read_only = 1;
}
/*
This represent one bootable linux configyration
*/
class LILO_CONF: public ARRAY_OBJ{
public:
char must_be_deleted; // Is this entry obsoleted
LILO_PARM parm;
SSTRING image;
SSTRING label;
/*~PROTOBEG~ LILO_CONF */
public:
LILO_CONF (void);
/*~PROTOEND~ LILO_CONF */
};
PUBLIC LILO_CONF::LILO_CONF()
{
must_be_deleted = 0;
}
class LILO_CONFS: public ARRAY{
/*~PROTOBEG~ LILO_CONFS */
public:
LILO_CONF *getitem (int no);
/*~PROTOEND~ LILO_CONFS */
};
PUBLIC LILO_CONF *LILO_CONFS::getitem(int no)
{
return (LILO_CONF*)ARRAY::getitem(no);
}
class LILO_OTHER: public ARRAY_OBJ{
public:
SSTRING label;
SSTRING partition;
};
class LILO_OTHERS: public ARRAY{
/*~PROTOBEG~ LILO_OTHERS */
public:
LILO_OTHER *getitem (int no);
/*~PROTOEND~ LILO_OTHERS */
};
PUBLIC LILO_OTHER *LILO_OTHERS::getitem(int no)
{
return (LILO_OTHER*)ARRAY::getitem(no);
}
/* #Specification: lilo.conf / how it works
The lilo.conf file is splitted in two sections. The first
contain the global or default setting. This section
act as a default for the rest of the file. This section ends
with the first "image = " or "other = " statement.
Global settings are:
#
compact
delay
boot = ...
#
Default setting that can be overriden in the followings
image= are
#
ramdisk = x
read-only
read-write
root = ...
vga = ...
#
*/
struct LILO_CUR{
LILO_CONF *conf;
LILO_PARM *parm;
LILO_OTHER *other;
int noline;
};
class LILO {
SSTRING boot; // On which device to place the boot code
char compact; //Special boot mode
int delay; // Delay in second or 0 for no delay
LILO_PARM def; // Default value
SSTRING message; // Path of the message file
LILO_CONFS confs;
LILO_OTHERS others;
char prefix[PATH_MAX];
public:
char isvalid; // Tell if the configuration is usable or present
char isused; // Is LILO used on this computer
/*~PROTOBEG~ LILO */
public:
LILO (void);
void addkernel (const char *def_src,
const char *def_name);
private:
void compute_prefix (void);
public:
int edit (void);
LILO_CONF *getconffromlabel (const char *lab);
private:
void makecfgpath (const char *path, char *realpath);
void parse_eq (const char *keyw,
const char *vals,
LILO_CUR&cur);
void parse_single (const char *pt, LILO_CUR&cur);
public:
int save (void);
void setdefault (void);
private:
void setupedit (DIALOG&dia);
void setupparm (DIALOG&dia, LILO_PARM&p);
public:
int updateif (void);
private:
int validate (int &nof);
protected:
void writeparm (FILE *fout,
LILO_PARM&p,
int global_parm);
public:
/*~PROTOEND~ LILO */
};
/*
Parse keyword with a value
*/
PRIVATE void LILO::parse_eq(
const char *keyw,
const char *vals,
LILO_CUR &cur)
{
vals = str_skip (vals);
char word[100];
str_copyword (word,keyw);
int numval = atoi(vals);
if (strcmp(word,"ramdisk")==0){
cur.parm->ramdisk = numval;
}else if (strcmp(word,"delay")==0){
delay = numval;
}else if (strcmp(word,"boot")==0){
boot.setfrom (vals);
}else if (strcmp(word,"vga")==0){
cur.parm->vga.setfrom (vals);
}else if (strcmp(word,"message")==0){
message.setfrom (vals);
}else if (strcmp(word,"root")==0){
cur.parm->root.setfrom (vals);
}else if (strcmp(word,"append")==0){
cur.parm->append.setfrom (vals);
}else if (strcmp(word,"label")==0){
if (cur.conf != NULL){
cur.conf->label.setfrom (vals);
}else if (cur.other != NULL){
cur.other->label.setfrom (vals);
}else{
xconf_error ("Misplaced \"label\" statement\n"
"in file %s, line %d",f_lilo.getpath()
,cur.noline);
}
}else if (strcmp(word,"image")==0){
cur.conf = new LILO_CONF;
cur.other = NULL;
confs.add (cur.conf);
cur.conf->image.setfrom (vals);
cur.parm = &cur.conf->parm;
cur.parm->read_only = def.read_only;
}else if (strcmp(word,"other")==0){
cur.other = new LILO_OTHER;
cur.conf = NULL;
others.add (cur.other);
cur.other->partition.setfrom (vals);
}
}
/*
Interpret single word parameter line
*/
PRIVATE void LILO::parse_single(const char *pt, LILO_CUR &cur)
{
char word[100];
str_copyword (word,pt);
if (strcmp(word,"compact")==0){
compact = 1;
}else if (strcmp(word,"read-only")==0){
cur.parm->read_only = 1;
}else if (strcmp(word,"read-write")==0){
cur.parm->read_only = 0;
}
}
PRIVATE void LILO::compute_prefix()
{
/* #Specification: lilo / moving lilo.conf
Linuxconf check carefully the path of the configuration
file (normally /etc/lilo.conf but changeable by the
user).
We assume that the path of the /boot/map is fairly
fixed. The only option used with lilo is -r (by
linuxconf at least), so lilo.conf is somewhere in
a "etc" directory and the file "map" is somewhere
in a "boot" directory right near this "etc".
*/
const char *path = f_lilo.getpath();
static char stdconf[]= ETC_LILO_CONF;
if (strcmp (path,stdconf)==0){
prefix[0] = '\0';
}else{
int len = strlen(stdconf);
int newlen = strlen(path);
int offset = newlen - len;
if (newlen < len
|| strcmp(path+offset,stdconf)!=0){
xconf_error (MSG_U(E_IVLDPATH
,"Invalid path of lilo.conf: %s\n"
"expected something at least as long\n"
"as %s\n"
"and ending with %s")
,path,stdconf,stdconf);
isvalid = 0;
}else{
strncpy (prefix,path,offset);
prefix[offset] = '\0';
}
}
}
static char LILOCFG[]="lilo";
static char ISUSED[]="isused";
/*
Load and parse the /etc/lilo.conf configuration file
*/
PUBLIC LILO::LILO()
{
isvalid = 0;
compact = 0;
delay = 0;
/* #Specification: lilo / disabling allowed
As a default, linuxconf assume lilo is used to
boot this computer. A check box allows the admin
to turn lilo off. Linuxconf won't bother the check
lilo further.
*/
isused = linuxconf_getvalnum (LILOCFG,ISUSED,1);
FILE *fin = f_lilo.fopen ("r");
if (fin != NULL){
char buf[1000];
LILO_CUR cur;
cur.parm = &def;
cur.conf = NULL;
cur.other = NULL;
cur.noline = 0;
/* #Specification: /etc/lilo.conf / comments
Comments are not preserved when editing lilo.conf
*/
isvalid = 1;
while (fgets_strip(buf,sizeof(buf)-1,fin,&cur.noline)!=NULL){
strip_end (buf);
char *pt = str_skip (buf);
if (*pt != '#' && *pt != '\0'){
char *pteq = strchr(pt,'=');
if (pteq != NULL){
*pteq++ = '\0';
parse_eq (pt,pteq,cur);
}else{
parse_single(pt,cur);
}
}
}
fclose (fin);
}
compute_prefix();
}
/*
Locate one setup from its label
*/
PUBLIC LILO_CONF *LILO::getconffromlabel (const char *lab)
{
LILO_CONF *ret = NULL;
for (int i=0; i<confs.getnb(); i++){
LILO_CONF *c = confs.getitem(i);
if (c->label.cmp(lab)==0){
ret = c;
break;
}
}
return ret;
}
/*
Build a path using a path relative to the /etc/lilo.conf file.
*/
PRIVATE void LILO::makecfgpath(const char *path, char *realpath)
{
if (prefix[0] == '\0'){
strcpy (realpath,path);
}else{
strcpy (realpath,prefix);
strcat (realpath,path);
}
}
static void writeif (FILE *fout, SSTRING &s, const char *keyw)
{
if (!s.is_empty()) fprintf (fout," %s = %s\n",keyw,s.get());
}
PROTECTED void LILO::writeparm(
FILE *fout,
LILO_PARM &p,
int global_parm) // Is p LILO::parm or
// one of the LILO_CONF::parm ?
{
/* #Specification: lilo / writing lilo.conf / normalising
linuxconf is not writing back lilo.conf in the same
way it was read. It is somewhat normalising it.
If for example, one setup has the same definitions
than the default setup, the definition are not repeated.
This feature is transparent to the user though. It make
the file lilo.conf smaller and easier to read manually.
*/
if (global_parm || p.ramdisk != def.ramdisk){
fprintf (fout," ramdisk = %d\n",p.ramdisk);
}
if (p.vga.is_empty()){
if (global_parm) fputs (" vga = normal\n",fout);
}else{
fprintf (fout," vga = %s\n",p.vga.get());
}
writeif (fout,p.append,"append");
if (global_parm || def.root.is_empty()){
writeif (fout,p.root,"root");
}else if (!p.root.is_empty()
&& p.root.cmp(def.root)!=0){
writeif (fout,p.root,"root");
}
if (global_parm || p.read_only != def.read_only){
fputs (p.read_only ? " read-only\n" : " read-write\n"
,fout);
}
}
/*
Write back the /etc/lilo.conf file.
Return -1 if any error.
*/
PUBLIC int LILO::save()
{
int ret = -1;
FILE *fout = f_lilo.fopen ("w");
if (fout != NULL){
fprintf (fout,"boot = %s\n",boot.get());
if (delay != 0) fprintf (fout,"delay = %d\n",delay);
if (compact) fprintf (fout,"compact\n");
writeif (fout,message,"message");
writeparm (fout,def,1);
int i;
for (i=0; i<confs.getnb(); i++){
LILO_CONF *c = confs.getitem(i);
if (!c->image.is_empty() && !c->must_be_deleted){
fprintf (fout,"image = %s\n",c->image.get());
fprintf (fout," label = %s\n",c->label.get());
writeparm (fout,c->parm,0);
}
}
for (i=0; i<others.getnb(); i++){
LILO_OTHER *c = others.getitem(i);
if (!c->partition.is_empty()){
fprintf (fout,"other = %s\n"
,c->partition.get());
fprintf (fout," label = %s\n"
,c->label.get());
}
}
ret = fclose (fout);
linuxconf_replace (LILOCFG,ISUSED,isused);
linuxconf_save();
}
return ret;
}
static void lilo_setpart (FIELD_COMBO *comb)
{
PARTITIONS *parts = partition_load();
for (int i=0; i<parts->getnb(); i++){
PARTITION *p = parts->getitem(i);
char str[80];
p->formatinfo (str);
comb->addopt(p->getdevice(),str);
}
}
/*
Dispose the parameter of a configuration or the default ones.
*/
PRIVATE void LILO::setupparm (DIALOG &dia, LILO_PARM &p)
{
FIELD_COMBO *comb = dia.newf_combo (MSG_U(F_ROOTPART,"root partition")
,p.root);
lilo_setpart (comb);
dia.newf_num (MSG_U(F_RAMSIZE,"Ramdisk size"),p.ramdisk);
dia.newf_chk (MSG_U(F_BOOTMODE,"boot mode"),p.read_only,"Read only");
comb = dia.newf_combo (MSG_U(F_VGA,"VGA mode"),p.vga);
comb->addopt (MSG_U(F_NORMAL,"normal"),MSG_U(F_STD8025,"standard 80x25"));
dia.newf_str (MSG_U(F_BOOTOPT,"Boot options"),p.append);
}
/*
Dispose the dialog
*/
PRIVATE void LILO::setupedit (DIALOG &dia)
{
dia.newf_chk ("",isused,MSG_U(F_LILOUSED
,"LILO is used to boot this system"));
FSTAB fstab;
FIELD_COMBO *comb = dia.newf_combo (MSG_U(F_INSTBOOT
,"Install boot sector on"),boot);
comb->addopt (fstab.getrootdev(),MSG_U(F_BOOTREC
,"boot record of the current root partition"));
comb->addopt ("/dev/hda",MSG_U(F_MASTERIDE
,"Master boot record on IDE systems"));
comb->addopt ("/dev/sda",MSG_U(F_MASTERSCSI
,"Master boot record on SCSI systems"));
comb->addopt (MSG_U(F_FD0,"/dev/fd0"),"");
lilo_setpart (comb);
dia.newf_chk (MSG_U(F_BIOSMODE,"Bios boot mode"),compact,"Compact");
dia.newf_num (MSG_U(F_BOOTDELAY,"Boot delay in 1/10 of seconds"),delay);
dia.newf_str (MSG_U(F_MSGFILE,"Message file(opt)"),message);
dia.newf_title ("",MSG_U(T_DEFAULTS,"Defaults"));
setupparm (dia,def);
/* #Specification: LILO editing / empty slots
Linuxconf always add two more LILO_CONF records
and two LILO_OTHER records, so the user is able
to fill new one. Ideally a special buttons would
be needed.
*/
int i;
for (i=0; i<2; i++){
LILO_CONF *conf = new LILO_CONF;
conf->parm.read_only = def.read_only;
confs.add (conf);
}
for (i=0; i<2; i++)others.add (new LILO_OTHER);
dia.newf_title ("",MSG_U(T_SETUPS,"Linux setups"));
for (i=0; i<confs.getnb(); i++){
if (i == 0){
dia.newf_title ("",MSG_U(F_DEFBOOT,"Defaut Linux boot"));
}else{
dia.newf_title ("","-");
}
LILO_CONF *c = confs.getitem(i);
dia.newf_chk ("",c->must_be_deleted
,MSG_U(F_DELCFG,"Delete this configuration"));
dia.newf_str (MSG_U(F_LABEL,"Label"),c->label);
dia.newf_str (MSG_U(F_KERNELIMAGE,"Kernel image file"),c->image);
setupparm (dia,c->parm);
}
dia.newf_title ("",MSG_U(F_OTHEROS,"Other operating systems"));
for (i=0; i<others.getnb(); i++){
if (i != 0) dia.newf_title ("","-");
LILO_OTHER *c = others.getitem(i);
dia.newf_str (MSG_R(F_LABEL),c->label);
FIELD_COMBO *comb = dia.newf_combo (MSG_U(F_PARTBOOT
,"partition to boot")
,c->partition);
lilo_setpart (comb);
}
}
static int validate_parm(
LILO_PARM &p,
int complain_if_empty)
{
PARTITIONS *parts = partition_load();
int ret = -1;
if (!p.root.is_empty()){
const char *pr = p.root.get();
PARTITION *e = parts->getitem(pr);
if (strncmp(pr,"/dev/fd",7)==0){
ret = 0;
}else if (e == NULL || !e->islinux()){
xconf_error (MSG_U(E_IVLDPART,"Partition %s is either invalid\n"
"or not a linux partition\n"),pr);
}else{
ret = 0;
}
}else if(complain_if_empty){
xconf_error (MSG_U(E_ROOTPNEED,"You must specify the root partition"));
}else{
ret = 0;
}
return ret;
}
/*
Sanity check of the complete configuration
Return -1 if any error.
nof will contain the number of the faulty field.
*/
PRIVATE int LILO::validate(int &nof)
{
validate_parm (def,0);
int i;
int ret = 0;
PARTITIONS *parts = partition_load();
if (boot.cmp("/dev/fd0")!=0
&& boot.cmp("/dev/hda")!=0
&& boot.cmp("/dev/sda")!=0
&& parts->getitem(boot.get())==NULL){
xconf_error (MSG_U(E_IVLSECTOR
,"Invalid partition or device for boot sector\n"
"installation"));
nof = 0;
ret = -1;
}
if (ret == 0){
for (i=0; i<confs.getnb() && ret == 0; i++){
LILO_CONF *c = confs.getitem(i);
if (!c->image.is_empty() && !c->must_be_deleted){
ret = validate_parm (c->parm
,def.root.is_empty());
// This computation is completly dependant on
// the dialog layout.
if (ret != 0) nof = i*8 + 13;
}
}
}
return ret;
}
PUBLIC int LILO::edit()
{
int nof = 0;
int ret = -1;
while (1){
DIALOG dia;
setupedit (dia);
MENU_STATUS code = dia.edit (
MSG_U(T_LILOCONF,"LInux LOader configuration")
,MSG_U(I_LILOCONF,"You are allowed to specify\n"
"-how it boots\n"
"-where (which partition)\n"
"-and what (LILO can boot almost any OS)")
,help_lilo
,nof
,MENUBUT_ACCEPT|MENUBUT_CANCEL|MENUBUT_INS);
if (code == MENU_ESCAPE || code == MENU_CANCEL){
break;
}else if (code == MENU_INS){
confs.insert (0,new LILO_CONF);
}else if (code == MENU_ACCEPT){
if (validate(nof)!=-1){
ret = save();
break;
}
}
}
return ret;
}
int lilo_edit ()
{
LILO lilo;
int ret = lilo.edit();
if (ret == 0) lilo.updateif();
return ret;
}
/*
Exec /sbin/lilo if needed.
Return 0 if not need, or -1 if any error.
*/
PUBLIC int LILO::updateif()
{
char path[PATH_MAX];
makecfgpath ("/boot/map",path);
long confdate = f_lilo.getdate ();
long mapdate = file_date (path);
int ret = 0;
/* #Specification: lilo / update needed if
If the file /etc/lilo.conf is newer than /boot/map
then the command lilo must be executed.
kernel files are also checked. If they are newer than
/boot/map, lilo has to be executed as this situation
may yield a non bootable system. Simply copying over
a kernel image may create a mismatch in /boot/map
and the actual layout of the kernel on the disk
*/
int needed = 0;
if (confdate > mapdate){
needed = 1;
}else{
// Check all kernel to see if they are newer
// Failing
for (int i=0; i<confs.getnb(); i++){
LILO_CONF *c = confs.getitem(i);
makecfgpath (c->image.get(),path);
long image_date = file_date (path);
if (image_date > mapdate){
needed = 1;
break;
}
}
}
if (needed){
char buf[PATH_MAX];
buf[0] = '\0';
if (prefix[0] != '\0') sprintf (buf,"-r %s",prefix);
if (simul_ison()
|| xconf_yesno(MSG_U(T_ACTLILO,"Activating LILO configuration")
,MSG_U(Q_ACTLILO,"Activating LILO change the way your\n"
"machine is booting.\n"
"Do I activate the configuration ?")
,help_lilo)==MENU_YES){
ret = netconf_system_if ("lilo",buf);
}else{
ret = 0;
}
}
return ret;
}
/*
Check if the lilo command must be executed
*/
int lilo_update ()
{
int ret = 0;
DAEMON *dae = daemon_find("lilo");
if (dae != NULL && dae->is_managed()){
LILO lilo;
if (lilo.isvalid && lilo.isused) ret = lilo.updateif();
}
return ret;
}
/*
Add a new kernel to the current configuration
*/
PUBLIC void LILO::addkernel(
const char *def_src, // Default path for the kernel
const char *def_name) // Default name for kernel file
{
DIALOG dia;
SSTRING kernel_src (def_src);
SSTRING kernel_dst;
SSTRING label;
char install = 0;
dia.newf_str (MSG_R(F_KERNELIMAGE),kernel_src);
dia.newf_radio (MSG_U(F_HOWBOOT,"How it boots"),install,0
,MSG_U(F_NEWDEFAULT,"new default bootable setup"));
dia.newf_radio (" ",install,1
,MSG_U(F_REPLCUR,"replace the current bootable setup"));
dia.newf_radio (" ",install,2,MSG_U(F_SELSETUP,"selectable setup"));
dia.newf_str (MSG_R(F_LABEL),label);
if (prefix != '\0' ){
kernel_dst.setfrom (prefix);
kernel_dst.append ("/");
}
kernel_dst.append (def_name);
dia.newf_str (MSG_U(F_WHERETOCOPY,"Where to copy the kernel file")
,kernel_dst);
LILO_PARM newparm = def;
dia.newf_title ("",MSG_U(F_OPTIONS,"Options"));
setupparm (dia,newparm);
int nof = 0;
while (1){
int len_prefix = strlen(prefix);
MENU_STATUS code = dia.edit (
MSG_U(T_ADDINGKERN,"Adding a new kernel to LILO")
,MSG_U(I_ADDINGKERN
,"You have already a working LILO\n"
"and you want to upgrade your kernel")
,help_lilo
,nof);
if (code == MENU_CANCEL || code == MENU_ESCAPE){
break;
}else if (kernel_src.is_empty()){
xconf_error (MSG_U(E_KERNNEEDED,"You must specify a kernel file"));
nof = 0;
}else if (install != 1
&& label.is_empty()){
xconf_error (MSG_U(E_LABELNEEDED,"You must specify a label"));
nof = 4;
}else if (install != 1
&& getconffromlabel(label.get())!=NULL){
xconf_error (MSG_U(E_LABELEXIST,"The label is already used"));
nof = 4;
}else if (!file_exist(kernel_src.get())){
xconf_error (MSG_U(E_ENOENT,"File %s does not exist")
,kernel_src.get());
nof = 0;
}else if (kernel_dst.getlen() <= len_prefix
|| kernel_dst.ncmp(prefix,len_prefix)!=0
|| kernel_dst.get()[len_prefix] != '/'){
xconf_error (MSG_U(E_BADPATH,"Bad path, must be under %s/")
,prefix);
nof = 5;
}else if (validate_parm(newparm,def.root.is_empty())==-1){
nof = 7;
}else if (kernel_dst.cmp(kernel_src)==0
|| !file_exist(kernel_dst.get())
|| xconf_yesno(MSG_U(T_REPLACE,"Replace existing kernel file")
,MSG_U(I_REPLACE,"ok to overwrite it ?")
,help_lilo)==MENU_YES){
file_copy (kernel_src.get(),kernel_dst.get());
LILO_CONF *conf = confs.getitem(0);
if (install != 1 || conf == NULL){
conf = new LILO_CONF;
if (install == 0){
confs.insert (0,conf);
}else{
confs.add (conf);
}
}
conf->parm = newparm;
conf->label.setfrom(label);
conf->image.setfrom(kernel_dst.get()+len_prefix);
if (save() != -1) lilo_update();
break;
}
}
}
/*
Let the user install a new kernel he just compiled
*/
void lilo_addcompil()
{
static char std_image[]="/usr/src/linux/arch/i386/boot/zImage";
if (!file_exist (std_image)){
xconf_error (MSG_U(E_NOCOMPILED
,"No kernel recently compiled available"));
}else{
FILE *fin = f_makefile.fopen ("r");
if (fin != NULL){
char name[30];
name[0] = '\0';
char buf[300];
int version = -1;
int patchlevel = -1;
int sublevel = -1;
while (fgets(buf,sizeof(buf)-1,fin)!=NULL){
char *pt = strchr (buf,'=');
/* #Specification: lilo / /usr/src/linux/Makefile / assumption
To help lilo admin set a proper name for his
kernel file, we read /usr/src/linux/Makefile
to grab PATCHLEVEL and SUBLEVEL. We assume
that the Makefile has the following lines
at the beginning.
#
VERSION = x
PATCHLEVEL = y
SUBLEVEL = z
#
The order is not important.
*/
if (pt != NULL){
pt = str_skip(pt+1);
if (strncmp(buf,"VERSION",7)==0){
version = atoi(pt);
}else if (strncmp(buf,"PATCHLEVEL",10)==0){
patchlevel = atoi(pt);
}else if (strncmp(buf,"SUBLEVEL",8)==0){
sublevel = atoi(pt);
}
if (version != -1
&& patchlevel != -1
&& sublevel != -1){
sprintf (name,"kernel-%d.%d.%d"
,version,patchlevel,sublevel);
break;
}
}
}
fclose (fin);
LILO lilo;
lilo.addkernel(std_image,name);
}
}
}
/*
Let the user install a new kernel he got from anywhere
*/
void lilo_addany()
{
LILO lilo;
lilo.addkernel("","");
}
/*
Let the user pick a different default boot configuration
*/
PUBLIC void LILO::setdefault()
{
DIALOG dia;
for (int i=0; i<confs.getnb(); i++){
LILO_CONF *c = confs.getitem(i);
dia.new_menuitem (c->label,c->image);
}
while (1){
int choice = 0;
MENU_STATUS code = dia.editmenu(
MSG_U(T_DEFKERN,"Default kernel configuration")
,MSG_U(I_DEFKERN,"Pick the configuration which will become\n"
"the default LILO configuration\n"
"The first one is currently the default")
,help_lilo
,choice,0);
if (code == MENU_QUIT || code == MENU_ESCAPE){
break;
}else if (code == MENU_OK){
if (choice != 0){
LILO_CONF *c = confs.getitem(choice);
confs.remove (c);
confs.insert (0,c);
if (save() != -1) lilo_update();
}
break;
}
}
}
void lilo_setdefault()
{
LILO lilo;
lilo.setdefault();
}